<?php

namespace App\Http\Middleware\Common;

use App\Error\BaseError;
use App\Error\General\RequestParametersError;
use App\Exceptions\KfHttpResponseException;
use Closure;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class VerifySignature
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return Response|RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        self::verifySignature($request);
        return $next($request);
    }

    /**
     * 验证基础签名字段
     *
     * @param Request $request
     * @return array|string
     */
    public static function checkSignField(Request $request)
    {
        $signFieldExists = $request->has("sign");
        if (!$signFieldExists) {
            throw new KfHttpResponseException(RequestParametersError::MISSING_VALIDATION_SIGNATURE_FIELD);
        }
        $requestSign = $request->get("sign", null);
        if (empty($requestSign)) {
            throw new KfHttpResponseException(RequestParametersError::VALIDATION_SIGNATURE_FIELD_CANNOT_BE_EMPTY);
        }
        return $requestSign;
    }

    /**
     * 校验签名
     *
     * @param Request $request
     * @return bool
     */
    public function verifySignature(Request $request): bool
    {
        $requestParams       = $request->all();
        $requestSign         = self::checkSignField($request);
        $filterRequestParams = collect($requestParams)->filter(function ($v, $key) {
            if ($v === null || in_array($key, ["s", "sign", "resourceId", "title"])) {
                return false;
            }

            if (is_array($v) && empty($v)) {
                return false;
            }

            if (is_string($v) && strlen($v) == 0) {
                return false;
            }

            return true;
        })->toArray();

        if (empty($filterRequestParams)) {
            throw new KfHttpResponseException(RequestParametersError::REQUEST_PARAMETERS_MISSING);
        }

        ksort($filterRequestParams);
        $sign = md5(json_encode($filterRequestParams, JSON_UNESCAPED_UNICODE) . "sign");
        if ($sign != $requestSign) {
            throw new KfHttpResponseException(BaseError::INVALID_SIGNATURE);
        }
        return true;
    }
}
